package com.zxc.mallProduct.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zxc.common.page.PageData;
import com.zxc.common.service.BaseService;
import com.zxc.common.service.CrudService;
import com.zxc.common.service.impl.CrudServiceImpl;
import com.zxc.mallProduct.dao.CategoryDao;
import com.zxc.mallProduct.dto.CategoryDTO;
import com.zxc.mallProduct.entity.CategoryEntity;
import com.zxc.mallProduct.service.CategoryService;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品三级分类
 *
 * @author zxc 341219181@gmail.com
 * @since 1.0.0 2022-12-16
 */
@Service
public class CategoryServiceImpl extends CrudServiceImpl<CategoryDao, CategoryEntity, CategoryDTO> implements CategoryService {

    @Override
    public QueryWrapper<CategoryEntity> getWrapper(Map<String, Object> params){
        String id = (String)params.get("id");

        QueryWrapper<CategoryEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id);

        return wrapper;
    }

    /**
     * 以树形结构来显示商品系统信息
     * @param params
     * @return
     */
    @Override
    public List<CategoryDTO> listWithTree(Map<String, Object> params) {
        // 1.查出全部商品
        // (由于后续需要使用流式编程stream，使用List集合来存储)
        List<CategoryDTO> allData = page(params).getList();
        // 2.组装成父子的树形结构
        // 主菜单 ：寻找到所有的一级分类
        List<CategoryDTO> levelMenus = allData.stream()
                // list集合，（流式计算）《===》 使用.filter过滤器获取所有的一级目录
                .filter(data -> data.getParentCid() == 0)
                // 遍历所有一级分类的商品属性，来寻找其对应的子菜单
                .map((menu) -> {
                    // 获取当前菜单属性下所属的所有子菜单
                    menu.setChildren(getChridren(menu , allData));
                    return menu;
                })
                .sorted((menu1 , menu2) -> {
                    // 即，此处的menu.getSort()会出现null的情况
                    return (menu1.getSort() == null ? 0 : menu1.getSort())
                            - (menu2.getSort() == null ? 0 : menu2.getSort() );
                })
                // 以Collection集合形式将所获取到的结果进行返回
                .collect(Collectors.toList());

        return levelMenus;
    }

    /**
     * 根据id数组，来对于菜单数据进行删除
     * @param ids
     */
    @Override
    public void removeMenuByIds(Long[] ids) {
        //TODO 检查当前删除的菜单，是否被别的地方引用

        delete(ids);
    }

    /**
     * 递归获取当前菜单元素的所有子菜单
     * @return
     */
    private List<CategoryDTO> getChridren(
            CategoryDTO currentData , List<CategoryDTO> allData){
        // 所传递的参数 ：当前正在遍历的菜单元素，同时所有的菜单元素数据

        // 子菜单 ：寻找到当前菜单元素下的所有子元素
        // 即，传递进来的数据为（1）菜单中的所有元素 （2）当前正在遍历的菜单元素
        // 寻找子菜单 ：即，通过遍历菜单中的所有元素，若其的父元素为当前正在遍历的菜单元素的话，即寻找到当前正在遍历菜单元素的某个子元素；
        List<CategoryDTO> allChildren = allData.stream().filter(
                        // 1.遍历所有菜单元素，寻找满足条件：其父元素 == 当前正在遍历的菜单元素
                        data -> data.getParentCid() == currentData.getCatId())
                .map((menu) -> {
                    // 递归遍历出所有的子菜单元素
                    menu.setChildren(getChridren(menu, allData));
                    return menu;
                })
                .sorted((menu1 , menu2) -> {
                    // 即，此处的menu.getSort()会出现null的情况
                    // 特殊情况 ：当当前比哪里的菜单元素没有子元素时，由于是递归获取当前菜单元素的所有子菜单
                    // 若是需要去避免menu.getSort()取到null（空值的情况），即当其为null时，赋予其默认值即可。
                    return (menu1.getSort() == null ? 0 : menu1.getSort())
                            - (menu2.getSort() == null ? 0 : menu2.getSort() );
                })
                .collect(Collectors.toList());
        return allChildren;
    }
}